﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Avivo.Common;
using Dokan;
using Microsoft.SmartDevice.Connectivity;

namespace Avivo.Models
{
	public class MountModel
	{
		public MountModel()
		{
			this.Status = new List<MountDeviceStatus>();
		}

		public List<MountDeviceStatus> Status
		{
			get;
			protected set;
		}

		public IEnumerable<Device> GetDevices()
		{
			var manager = new DatastoreManager(CultureInfo.CurrentCulture.LCID);
			var platforms = manager.GetPlatforms();
			foreach (var platform in platforms)
			{
				var devices = platform.GetDevices();
				foreach (var device in devices)
				{
					yield return device;
				}
			}
		}

		public bool IsMounted(Device device)
		{
			var status = this.Status.FirstOrDefault(x => x.DeviceId == device.Id);
			return (status != null ? status.IsMounted : false);
		}

		public void Mount(Device device, Action<Exception> callback = null)
		{
			var status = this.Status.FirstOrDefault(x => x.DeviceId == device.Id);
			if (status != null && status.IsMounted)
			{
				//Already mounted
				return;
			}

			var worker = new BackgroundWorker();
			worker.DoWork += delegate
			{
				var fs = new IsolatedStorageOperations(device);

				char letter = Helper.GetFreeDriveLetter();
				var options = new DokanOptions
				{
					MountPoint = letter + ":\\",
					DebugMode = true,
					UseStdErr = true,
					NetworkDrive = false,
					RemovableDrive = true, //Provides an "eject"-menu to unmount
					UseKeepAlive = true, //Auto-unmount
					ThreadCount = (ushort)(Debugger.IsAttached ? 1 : 0), //Limit to one thread during debugging!
					VolumeLabel = device.Name //"WP7IsolatedStorage"
				};

				//Presume the virtual drive has been mounted
				if (status == null)
				{
					status = new MountDeviceStatus();
					status.DeviceId = device.Id;
					this.Status.Add(status);
				}
				status.DriveLetter = letter;
				status.IsMounted = true;

				if (callback != null)
				{
					callback(null);
				}

				int result = DokanNet.DokanMain(options, fs); //Blocking thread
				//switch (Math.Abs(result))
				//{
				//  case DokanNet.DOKAN_SUCCESS:
				//    if (status == null)
				//    {
				//      status = new MountDeviceStatus();
				//      status.Device = device;
				//      this.Status.Add(status);
				//    }
				//    status.DriveLetter = letter;
				//    status.IsMounted = true;
				//    break;

				//  default:
				//  case DokanNet.DOKAN_DRIVE_LETTER_ERROR:
				//  case DokanNet.DOKAN_DRIVER_INSTALL_ERROR:
				//  case DokanNet.DOKAN_MOUNT_ERROR:
				//  case DokanNet.DOKAN_START_ERROR:
				//  case DokanNet.DOKAN_ERROR:
				//    break;
				//}
			};
			worker.RunWorkerAsync();
		}

		public void Unmount(Device device)
		{
			var status = this.Status.FirstOrDefault(x => x.DeviceId == device.Id);
			if (status == null || !status.IsMounted)
			{
				//Already unmounted
				return;
			}

			int result = DokanNet.DokanUnmount(status.DriveLetter);
			//switch (Math.Abs(result))
			//{
			//  case DokanNet.DOKAN_SUCCESS:
			//    status.DriveLetter = default(char);
			//    status.IsMounted = false;
			//    break;

			//  default:
			//  case DokanNet.DOKAN_DRIVE_LETTER_ERROR:
			//  case DokanNet.DOKAN_DRIVER_INSTALL_ERROR:
			//  case DokanNet.DOKAN_MOUNT_ERROR:
			//  case DokanNet.DOKAN_START_ERROR:
			//  case DokanNet.DOKAN_ERROR:
			//    break;
			//}

			//Unmounted even if it throws DOKAN_ERROR
			status.DriveLetter = default(char);
			status.IsMounted = false;
		}

		public void Explore(Device device)
		{
			var status = this.Status.FirstOrDefault(x => x.DeviceId == device.Id);
			if (status == null || !status.IsMounted)
			{
				//Device unmounted, no action
				return;
			}

			var info = new ProcessStartInfo();
			info.FileName = "explorer.exe";
			info.Arguments = status.DriveLetter + ":\\";
			info.WorkingDirectory = status.DriveLetter + ":\\";

			var process = Process.Start(info);
		}

		public string GetDriveLetter(Device device)
		{
			var status = this.Status.FirstOrDefault(x => x.DeviceId == device.Id);
			if (status != null && status.IsMounted)
			{
				return status.DriveLetter != default(char) ? status.DriveLetter.ToString().ToUpper() : null;
			}
			return null;
		}

		public static void LaunchCalculator()
		{
			//Blog: http://dennisdel.com/blog/how-to-access-blacklisted-apps-in-the-windows-phone-emulator-rom-with-the-locked-bin-image
			//Video: http://www.youtube.com/watch?v=u6VrE5t2mRI
			//Reference: Microsoft.Smartdevice.Connectivity.dll

			var manager = new DatastoreManager(CultureInfo.CurrentCulture.LCID);
			var platforms = manager.GetPlatforms();
			var devices = platforms.First().GetDevices();
			var device = devices.First(); //Connected device
			//var device = devices.Last(); //Emulator
			device.Connect();

			//var apps = device.GetInstalledApplications();
			//foreach (var app in apps)
			//{
			//}

			//Calculator: 5B04B775-356B-4AA0-AAF8-6491FFEA5603
			const string guid = "5B04B775-356B-4AA0-AAF8-6491FFEA5603";
			device.GetApplication(new Guid(guid)).Launch();
		}
	}
}
